package blq.ssnb.redbagaide.service;

import android.accessibilityservice.AccessibilityService;
import android.app.Notification;
import android.app.PendingIntent;
import android.graphics.Rect;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;

import com.blq.snblib.util.DisplayUtil;
import com.blq.snblib.util.MLog;

import java.util.ArrayList;
import java.util.List;

public class RedBagService extends AccessibilityService {
    public static final String TAG = RedBagService.class.getSimpleName();

    //-------------微信相关
    /**
     * 微信包名
     */
    private static final String WECHAT_PACK_NAME = "com.tencent.mm";
    /**
     * 微信主界面。聊天界面
     */
    private static final String CLASS_WECHAT_MAIN = "com.tencent.mm.ui.LauncherUI";
    /**
     * 微信红包点开界面
     */
    private static final String CLASS_WECHAT_LUCKYMONEY_RECEIVE="com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyNotHookReceiveUI";
    /**
     * 微信红包抢到后跳转的详情界面
     */
    private static final String CLASS_WECHAT_LUCKYMONEY_DETAIL="com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI";

    /**
     * 红包关键词 “[微信红包]”
     */
    private static final String WECHAT_RED_BAG="[微信红包]";
    /**
     * 红包关键词 “领取红包”
     */
    private static final String WECHAT_GET_RED_BAG="微信红包";

    private static final String WECHAT_RED_BAG_DETAIL_BACK ="返回";

    //-------------参数
    /**
     * true 表示通知栏点击了 false 表示未点击通知栏
     */
    private boolean haveNotificationClick = false;
    /**
     * true 表示进入的 LauncherUI 界面 false 表示 当前界面已经在launcherUI中
     */
    private boolean isNewLaunchUI = false;
    /**
     * true 表示list滑动到了最底端
     */
    private boolean isScrollerLast = false;

    /**
     * 表示 有TextView是content内容改变
     */
//    private boolean isText2048 = false;
    //------QQ红包------
    private static final String QQ_PACK_NAME = "com.tencent.mobileqq";
    private static final String QQ_RED_BAG = "[QQ红包]";

    public RedBagService() {}

    @Override
    public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
        //如果是微信包名的话就进入事件分发
        if(accessibilityEvent.getPackageName().equals(WECHAT_PACK_NAME)){
            distributionEvent(accessibilityEvent);
        }
    }

    /**
     * 监听事件的分发
     * @param event 事件
     */
    private void distributionEvent(AccessibilityEvent event) {
        int eventType = event.getEventType();
        switch (eventType){
            //监听通知栏
            case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
                watchNotification(event);
                break;
            //监听界面变化
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
                watchWindowState(event);
                break;
            //监听界面内容变化
            case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
                watchWindowContent(event);
                break;
            case AccessibilityEvent.TYPE_VIEW_SCROLLED:
                watchListScroller(event);
                break;

        }
    }

    //-----------------------通知栏事件
    /**
     * 监事 通知栏 (用户不在微信界面或在微信界面不在红包聊天界面)
     * @param event 事件
     */
    private void watchNotification(AccessibilityEvent event) {
        List<CharSequence> texts = event.getText();//获得NOTIFICATION
        if(!texts.isEmpty()){//不为空
            for (CharSequence text : texts){//迭代
                String content = text.toString();//文本内容
                println("通知栏内容:"+content);
                if(isClickNotification(content,event)){
                    return;
                }
            }
        }
    }

    /**
     * 判断是否点击包含文字的通知栏
     * @param content 要匹配的文字
     * @param event 事件
     * @return true 点击了，false 未点击
     */
    private boolean isClickNotification(String content, AccessibilityEvent event){
        ////如果文本内容包含[微信红包]
        // 并且获得数据不为空
        // 并且是Notification类或其子类
        if(content.contains(WECHAT_RED_BAG)
                &&event.getParcelableData()!=null
                &&event.getParcelableData() instanceof Notification){
            try {
                ((Notification) event.getParcelableData()).contentIntent.send();//执行这个Intent（模拟点击）
                haveNotificationClick = true;//通知栏点击变为true
                return true;//返回掉 因为不可能同时点击两个Notification且微信进入后会把所有的通知取消
            } catch (PendingIntent.CanceledException e) {
                e.printStackTrace();
            }
        }
        return false;
    }
    //====================================
    //-----------------界面变化监听
    /**
     * 监听界面变化
     * @param event 事件
     */
    private void watchWindowState(AccessibilityEvent event) {
        String className = event.getClassName().toString();

        //当前进入的界面是否为主界面或聊天界面
        isNewLaunchUI = className.equals(CLASS_WECHAT_MAIN);
        println(className);
        if(className.equals(CLASS_WECHAT_LUCKYMONEY_RECEIVE)){
            //如果是抢红包界面点开界面
            openPacket();

        }else if(className.equals(CLASS_WECHAT_LUCKYMONEY_DETAIL)){
            //如果是抢红包详情界面
            recordInfo();
        }
    }
    //=======================================
    //--------------点开红包的 receive 界面相关

    /**
     * 开始抢红包
     */
    private void openPacket() {
        //获得根节点
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo != null) {//不为空
            if(!findOpenBtnAndOpen(nodeInfo)){
                //如果打开失败的话，就点击返回
                sleep(1000);
                luckyMoneyReceiveBack(nodeInfo);
            }
        }
    }

    /**
     * 找到红包开按钮并打开
     * @param nodeInfo 根节点
     * @return true 成功找到并打开
     *          false 未找到按钮或打开失败
     */
    private boolean findOpenBtnAndOpen(AccessibilityNodeInfo nodeInfo) {
//        String[] bagIds={"bag","ba_","bdg"};
//        String[] bagIds={"bag","ba_","c2i"};
//        boolean isOpen = clickView(nodeInfo,bagIds);
        boolean isOpen = false;
        if(!isOpen){//如果不能打开那么就找到是button的那个对象，然后代开他
            AccessibilityNodeInfo rootNode = getRootInActiveWindow();
            List<AccessibilityNodeInfo> btnNodes = findNodeInfoByClass(rootNode,"android.widget.Button");
            if(btnNodes!=null && btnNodes.size()>0){
                AccessibilityNodeInfo btnNode = btnNodes.get(0);
                if(btnNode!=null&&btnNode.isClickable()){
                    btnNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    isOpen=true;
                }
            }
        }
        return isOpen;
    }

    /**
     * 找到类型为 className 的对象
     * @param nodeInfo 节点对象
     * @param className 类型全称
     * @return 找到该类型的对象
     */
    private List<AccessibilityNodeInfo> findNodeInfoByClass(AccessibilityNodeInfo nodeInfo , String className){
        if(nodeInfo==null){
            return null;
        }

        if(nodeInfo.getChildCount()==0){
            if(className.equals(nodeInfo.getClassName())){
                List<AccessibilityNodeInfo> nodeInfos = new ArrayList<>();
                nodeInfos.add(nodeInfo);
                return nodeInfos;
            }else{
                return null;
            }
        }
        List<AccessibilityNodeInfo> objects = new ArrayList<>();
        for (int i = 0 ; i < nodeInfo.getChildCount();i++){
            List<AccessibilityNodeInfo> nodeinfos = findNodeInfoByClass(nodeInfo.getChild(i),className);
            if(nodeinfos!=null&&nodeinfos.size()!=0){
                objects.addAll(nodeinfos);
            }
        }
        return objects;
    }

    /**
     * 抢红包页面的返回按钮
     * @param nodeInfo 根节点
     */
    private void luckyMoneyReceiveBack(AccessibilityNodeInfo nodeInfo){
//        String[] receiveBackIds = {"bak","bdk"};
        String[] receiveBackIds = {"bak"};
        boolean isBack = clickView(nodeInfo,receiveBackIds);
        if(!isBack){
            AccessibilityNodeInfo rootNode = getRootInActiveWindow();
            List<AccessibilityNodeInfo> imgView = findNodeInfoByClass(rootNode,"android.widget.ImageView");
            if(imgView!=null){
                for (AccessibilityNodeInfo img:imgView){
                    if(img!=null&&img.isClickable()){
                        img.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    }
                }
            }
        }
    }

    /**
     * 点击给定界面下的id名称
     * id按顺序匹配，如果前面有一个匹配到了那么后面就不匹配直接返回true
     * 否者就继续查找view 直到匹配上或结束
     * @param nodeInfo 根节点
     * @param ids 匹配id
     * @return true 成功找到并打开
     *          false 未找到按钮或打开失败
     */
    private boolean clickView(AccessibilityNodeInfo nodeInfo,String[] ids){
        for (String id :ids){
            List<AccessibilityNodeInfo> list =findListById(nodeInfo,id);
            for (AccessibilityNodeInfo n : list) {
                println("desuce"+n.getContentDescription());
                if(n.isClickable()&&
                        n.isVisibleToUser()){
                    n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    return true;
                }
            }
        }
        return false;
    }
    //====================================
    //-------------抢到红包后的详情界面------------

    /**
     * 记录信息
     */
    private void recordInfo() {
        AccessibilityNodeInfo rootNode = getRootInActiveWindow();
        if(rootNode!=null){//当部位null的时候
            //记录抢到的钱，和谁的红包以及红包内容
//            String user = getUser(rootNode);
//            String money = getMoney(rootNode);
//            String detail = getDetail(rootNode);
//            println("红包详情："+ user+"\n"+money+"\n"+detail+"\n");
            //记录完了就返回
            sleep(1000);
            detailBack(rootNode);
        }
    }

    private String getUser(AccessibilityNodeInfo rootNode) {
        String[] userIds = {"b8w"};
        return getText(rootNode,userIds);
    }

    private String getMoney(AccessibilityNodeInfo rootNode) {
        String[] moneyIds = {"b90"};
        return getText(rootNode,moneyIds);
    }

    private String getDetail(AccessibilityNodeInfo rootNode) {
        String[] detailIds = {"b8y"};
        return getText(rootNode,detailIds);
    }

    private String getText(AccessibilityNodeInfo rootNode, String[] ids){
        String returnStr = "";
        for (String id :ids){
            List<AccessibilityNodeInfo> list =findListById(rootNode,id);
            for (AccessibilityNodeInfo n : list) {
                if(n.isVisibleToUser()
                        &&n.getText()!=null
                        &&!n.getText().toString().isEmpty()){
                    returnStr = n.getText().toString();
                    return returnStr;
                }

            }
        }
        return returnStr;
    }

    /**
     * 通过id和节点来找到该节点下的所有相同id的NodeInfo
     * @param rootNode 根节点
     * @param id 要找的id
     * @return 找到的结果
     */
    private List<AccessibilityNodeInfo> findListById(AccessibilityNodeInfo rootNode ,String id){
        return rootNode.findAccessibilityNodeInfosByViewId(WECHAT_PACK_NAME+":id/"+id);
    }

    /**
     * 退出详情页面
     * @param rootNode 根节点
     */
    private void detailBack(AccessibilityNodeInfo rootNode) {
//        String[] detailBackIds={"fa","fs"};
        String[] detailBackIds={"fa","gw"};
        println("---------------------->>>>>");
        boolean isBack = clickView(rootNode,detailBackIds);
        println("======================>>>>>");
        if(!isBack){
            List<AccessibilityNodeInfo> details = rootNode.findAccessibilityNodeInfosByText(WECHAT_RED_BAG_DETAIL_BACK);
            if(details!=null&&details.size()==1){
                AccessibilityNodeInfo backBtn = details.get(0);
                backBtn = findClickInfo(backBtn);
                if(backBtn!=null &&backBtn.isClickable()){
                    backBtn.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                }
            }
        }
    }

    //====================================
    //-----------------------List滑动

    /**
     * 这个参数只有在这里使用，不能在其他地方使用
     */
    private AccessibilityNodeInfo lastRedBag;

    /**
     * 监听listView的滑动
     * @param event
     */
    private void watchListScroller(AccessibilityEvent event) {
        String className = event.getClassName().toString();
        //如果是在主界面或聊天界面
        if (isNewLaunchUI&&className.equals("android.widget.ListView")) {

            if(event.getToIndex()==event.getItemCount()-1){
                isScrollerLast=true;
                //如果滚动之前有text的改变
//                if(isText2048){
                    //如果当前滚动的是最后面一个
                    if(isLastMessageRedBag(event)) {//判断最后一个是否是红包
                        lastRedBag.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    }
//                }
//                isText2048=false;
            }else{
                isScrollerLast=false;
            }
        }
    }

    /**
     * 检查最后一条消息是否是红包
     * @param event 事件
     * @return true 表示是红包
     */
    private boolean isLastMessageRedBag(AccessibilityEvent event) {
        AccessibilityNodeInfo info = event.getSource();
        if (info==null){
            return false;
        }
        AccessibilityNodeInfo lastRedBag = findLastRedBag();
        if(lastRedBag==null){
            return false;
        }
        Rect sourceRect = new Rect();
        Rect rebBagRect = new Rect();
        info.getBoundsInScreen(sourceRect);
        lastRedBag.getBoundsInScreen(rebBagRect);
        this.lastRedBag = lastRedBag;
        return (sourceRect.bottom-rebBagRect.bottom)<DisplayUtil.dip2Px(getApplicationContext(),50);
    }

    //======================
    //-------当文本内容改变的时候---------

    /**
     * 监听界面内容变化
     *
     * @param event 事件
     */
    private void watchWindowContent(AccessibilityEvent event) {
        String className = event.getClassName().toString();

        //如果是通过通知栏进来的那么一定是进入到聊天界面的
        if(haveNotificationClick){
            AccessibilityNodeInfo lastRedBag = findLastRedBag();
            if (lastRedBag!=null){
                lastRedBag.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }
            haveNotificationClick = false;
        }else if(isNewLaunchUI){//否者的话判断当前界面是否是在聊天界面
            //判断最后一条记录是否是红包
            //如果是在聊天页面的话那么判断改变的是不是listview
            if(className.equals("android.widget.TextView")){
//                isText2048 = isScrollerLast;
            }
        }
    }

    /**
     * 找到当前页面的最后一个红包的可点击对象
     * @return “领取红包”字体所在的对象的可点击父类对象
     */
    private AccessibilityNodeInfo findLastRedBag(){
        AccessibilityNodeInfo rootNode = getRootInActiveWindow();
        if(rootNode==null){
            return null;
        }
        List<AccessibilityNodeInfo> redBags = rootNode.findAccessibilityNodeInfosByText(WECHAT_GET_RED_BAG);
        AccessibilityNodeInfo lastRedBagNode = null;
        if(redBags != null && !redBags.isEmpty()){
            lastRedBagNode = redBags.get(redBags.size()-1);
            lastRedBagNode = findClickInfo(lastRedBagNode);
        }
        return lastRedBagNode;
    }

    /**
     * 返回能被点击的节点
     * @param nodeInfo 初始对象
     * @return nodeInfo 或nodeInfo的父类，或者null
     */
    private AccessibilityNodeInfo findClickInfo(AccessibilityNodeInfo nodeInfo) {
        if(nodeInfo == null){
            return null;
        }
        return nodeInfo.isClickable()?nodeInfo:findClickInfo(nodeInfo.getParent());
    }

    //=============================

    @Override
    public void onInterrupt() {

    }

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
    }


    /**
     * 延迟线程
     * @param millis 延迟毫秒
     */
    private void sleep(int millis){
        if(true){
            return;
        }
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //---------------test-------
    private boolean isDebug = true;
    private void println(String msg){
        println(TAG,msg);
    }
    private void println(String TAG,String msg){
        if(isDebug){
            MLog.e(TAG,msg);
        }
    }
}
